// ----------------------------------
// RSDK Project: Sonic 1/Sonic 2
// Script Description: Stage Setup Object
// Script Author: Christian Whitehead/Simon Thomley
// Unpacked by Rubberduckycooly's script unpacker
// ----------------------------------

// Aliases

private alias saveRAM[399] : spindash.active	//63C SData.bin
private alias saveRAM[400] : peelout.active	//640 SData.bin
private alias saveRAM[401] : dropdash.active	//644 SData.bin
private alias saveRAM[402] : shilds.type	//648 SData.bin
private alias saveRAM[403] : music.type		//64C SData.bin
private alias saveRAM[404] : timer.type		//650 SData.bin
private alias saveRAM[405] : timeover.active	//654 SData.bin
private alias saveRAM[406] : flight.cancel	//658 SData.bin
private alias saveRAM[407] : region.type	//65C SData.bin
private alias saveRAM[408] : lives.amount	//660 SData.bin
private alias saveRAM[409] : tiger.active	//664 SData.bin

private alias 666 : GROUP_CUTSCENES
private alias object.visible : player.visible
private alias object.value18 : player.sortedDrawOrder

// Function declarations
reserve function StageSetup_HandleOscillationTable
reserve function TimeAttackReset

// Static Values
public value StageSetup_monitorOverlayFrame = 0;
public value StageSetup_oscillateFlipFlags = 0;
public value TARestartCooldown = 0;

// Tables
public table StageSetup_initOscillationTable
	128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0
	128, 0, 0x3848, 238, 0x2080, 180, 0x3080, 270, 0x5080, 450, 0x7080, 630, 128, 0, 0x4000, 254
end table

public alias StageSetup_oscillationTable : StageSetup_table9

public table StageSetup_oscillationTable
	128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0
	128, 0, 0x3848, 238, 0x2080, 180, 0x3080, 270, 0x5080, 450, 0x7080, 630, 128, 0, 0x4000, 254
end table

public table StageSetup_oscillateLimits
	2, 0x1000, 2, 0x1800, 2, 0x2000, 2, 0x3000, 4, 0x2000, 8, 0x800,  8, 0x4000, 4, 0x4000
	2, 0x3800, 2, 0x3800, 2, 0x2000, 3, 0x3000, 5, 0x5000, 7, 0x7000, 2, 0x4000, 2, 0x4000
end table


function StageSetup_HandleOscillationTable
	temp0 = 0
	temp1 = 0
	while temp0 < 16
		GetTableValue(temp4, temp1, StageSetup_oscillateLimits)		// temp4 = oscillateSpeed
		GetTableValue(temp6, temp1, StageSetup_oscillationTable)	// temp6 = oscillatePos
		temp1++

		GetTableValue(temp5, temp1, StageSetup_oscillateLimits)		// temp5 = oscillateMax
		GetTableValue(temp7, temp1, StageSetup_oscillationTable)	// temp7 = oscillateInc
		temp1--

		GetBit(temp2, StageSetup_oscillateFlipFlags, temp0)
		if temp2 == false
			temp7 += temp4
			temp6 += temp7
			if temp6 >= temp5
				SetBit(StageSetup_oscillateFlipFlags, temp0, true)
			end if
		else
			temp7 -= temp4
			temp6 += temp7
			if temp6 < temp5
				SetBit(StageSetup_oscillateFlipFlags, temp0, false)
			end if
		end if

		SetTableValue(temp6, temp1, StageSetup_oscillationTable)
		temp1++

		SetTableValue(temp7, temp1, StageSetup_oscillationTable)
		temp1++

		temp0++
	loop
end function


function TimeAttackReset
		if object.alpha < 255
			temp1 = inputPress.buttonL
			temp1 += inputPress.buttonR
			if temp1 == 2
				PlaySFX(SFXName[Teleport], 0)
				//temp1 = 0
			endif

			if ta.restarting == 0
				temp0 = inputDown.buttonL
				temp0 += inputDown.buttonR
				if temp0 == 2
					object.alpha += 16
				else
					if object.alpha > 0
						object.alpha -= 16
					endif
				endif
			end if
		else
			TA.quickstart = 1
			TARestartCooldown = 0
			ta.restarting = 1
			LoadStage()
		endif
end function

event ObjectMain
	if TARestartCooldown < 60
		TARestartCooldown++
	else
		TARestartCooldown = 60
	end if
	
	if options.gameMode == 1
		if stage.state != STAGE_PAUSED
			if object[30].type != TypeName[Act Finish]
				if TARestartCooldown == 60
					if object[currentPlayer].controlMode != -1
						callFunction(TimeAttackReset)
					end if
				end if
			end if
		end if
	endif
	switch stage.state
	case STAGE_PAUSED
	case STAGE_FROZEN
		// Do nothing
		break
	default
		// Handle Ring Frame
		ringTimer++
		if ringTimer == 4
			ringTimer = 0
			ringFrame++
			ringFrame &= 7
		end if

		// Handle Monitor overlay frame
		StageSetup_monitorOverlayFrame++
		if StageSetup_monitorOverlayFrame > 17
			StageSetup_monitorOverlayFrame = 0
		end if
		
		// Handle Player Score Bonus
		if options.gameMode != 2
			if player.score >= player.scoreBonus

				player.scoreBonus += 0xC350

				ResetObjectEntity(25, TypeName[Music Event], 2, 0, 0)
				object[25].priority = PRIORITY_ACTIVE
			end if
		end if

		// Handle Oscillations & Platform Array movements
		oscillation++
		oscillation &= 511
		CallFunction(StageSetup_HandleOscillationTable)
	
		if options.expertmode == 1
			timeover.active = 1
		else
			timeover.active = 0
		end if

		// Handle Time overs
		if timeover.active == 1
			if stage.minutes == 1

				CallFunction(PlayerObject_Kill)

			end if
		end if

		//Boundaries: Left & Bottom
		foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
			temp0 = object[currentPlayer].collisionLeft
			temp0 <<= 16
			temp0 += object[currentPlayer].xpos
			temp1 = stage.curXBoundary1
			temp1 <<= 16
			if temp0 < temp1
				if object[currentPlayer].right == true
					object[currentPlayer].xvel 	= 0x10000
					object[currentPlayer].speed = 0x10000
				else
					object[currentPlayer].xvel 	= 0
					object[currentPlayer].speed = 0
				end if

				object[currentPlayer].xpos = temp1
				temp0 = object[currentPlayer].collisionLeft
				temp0 <<= 16
				object[currentPlayer].xpos -= temp0
			end if

			temp1 = stage.curYBoundary2
			temp1 <<= 16
			if temp1 < stage.deathBoundary
				if object[currentPlayer].ypos > stage.deathBoundary
					CallFunction(PlayerObject_Kill)
				end if
			else
				if object[currentPlayer].ypos > temp1
					CallFunction(PlayerObject_Kill)
				end if
			end if
		next
	end switch

	// Handle Touch Controls
	if options.attractMode == false
		if object[0].controlMode > -1
			options.touchControls = true
		else
			options.touchControls = false
		end if
	else
		options.touchControls = false
	end if

	// Sort players, player 1 should always be on top of player 2
	currentPlayer = playerCount
	currentPlayer--
	while currentPlayer > -1
		if player[currentPlayer].visible == true
			currentPlayer += playerCount
			if player[currentPlayer].sortedDrawOrder == 0
				currentPlayer -= playerCount
				arrayPos0 = player[currentPlayer].sortedDrawOrder
				AddDrawListEntityRef(arrayPos0, currentPlayer)

				currentPlayer += playerCount
				AddDrawListEntityRef(arrayPos0, currentPlayer)
				currentPlayer -= playerCount
			else
				currentPlayer -= playerCount
				arrayPos0 = player[currentPlayer].sortedDrawOrder
				currentPlayer += playerCount
				AddDrawListEntityRef(arrayPos0, currentPlayer)

				currentPlayer -= playerCount
				arrayPos0 = player[currentPlayer].sortedDrawOrder
				AddDrawListEntityRef(arrayPos0, currentPlayer)
			end if
		end if
		currentPlayer--
	loop
end event

event ObjectDraw
	DrawRect(0, 0, screen.xsize, screen.ysize, 255, 255, 255, object.alpha)
	object.drawOrder = 6
end event

event ObjectStartup
	SetMusicTrack("SONIC_ACTCLEAR.ogg", 1, false)
	SetMusicTrack("INVINCIBILITY.ogg", 2, 1)
	SetMusicTrack("Continue.ogg", 3, false)
	SetMusicTrack("Boss.ogg", 4, 9081)
	SetMusicTrack("GAMEOVER.ogg", 5, false)
	SetMusicTrack("Drowning.ogg", 6, false)
	SetMusicTrack("Super.ogg", 7, true)

	stage.timeOver = false

	if options.attractMode == false
		// There is code here on the official PC version...
		// however! we don't have that!
	else
		//Set Object Range, changes internal bounds so attract mode always looks the same
		SetObjectRange(424)
	end if

	SpeedUpMusic 	= 0
	SlowDownMusic 	= 0
	stage.musicFlag = false

	stage.deathBoundary = stage.curYBoundary2
	stage.deathBoundary <<= 16

	foreach (TypeName[Stage Setup], arrayPos0, ALL_ENTITIES)
		ResetObjectEntity(arrayPos0, TypeName[Blank Object], 0, 0, 0)
	next
	object[8].type = TypeName[Stage Setup]
	object[8].priority = PRIORITY_ACTIVE_PAUSED	

	foreach (TypeName[HUD], arrayPos0, ALL_ENTITIES)
		object[arrayPos0].type = TypeName[Blank Object]
		if credits.screen == 0
			object[9].type 			= TypeName[HUD]
			object[9].priority 		= PRIORITY_ACTIVE
			object[9].drawOrder 	= 6
			object[9].propertyValue = object[arrayPos0].propertyValue
		end if
	next

	ringExtraLife 						= 100
	oscillation 						= 0
	StageSetup_oscillateFlipFlags 		= 0b1011111000000000

	temp0 = 0
	while temp0 < 32
		GetTableValue(temp1, temp0, StageSetup_initOscillationTable)
		SetTableValue(temp1, temp0, StageSetup_oscillationTable)
		temp0++
	loop

	if options.saveSlot > 0
		options.shieldType = 0
	end if

	blueShieldType = TypeName[Blue Shield]
	invincibilityType = TypeName[Invincibility]
end event

event RSDKDraw
	DrawSprite(0)
end event

event RSDKLoad
	LoadSpriteSheet("Global/Display.gif")
	SpriteFrame(-16, -16, 32, 32, 1, 143)
end event